#include "tlb.h"

static void init(TLB_t *this) {
	int i;
	for (i = 0; i < TLB_SIZE; ++i) {
		(this -> ctnr)[i].valid = false;
	}
}

static hwaddr_t read(TLB_t *this, lnaddr_t addr, bool *flag) {
	*flag = false;

	int i;
	uint32_t tag = addr >> 12;
	for (i = 0; i < TLB_SIZE; ++i) {
		if ((this -> ctnr)[i].valid && (this -> ctnr)[i].tag == tag) {
			*flag = true;
			return (this -> ctnr)[i].page_frame;
		}
	}

	return 0;
}

static void write(TLB_t *this, lnaddr_t addr, hwaddr_t page_frame) {
	int i;
	uint32_t tag = addr >> 12;
	for (i = 0; i < TLB_SIZE; ++i) {
		if (!((this -> ctnr)[i].valid)) {
			(this -> ctnr)[i].valid = true;
			(this -> ctnr)[i].tag = tag;
			(this -> ctnr)[i].page_frame = page_frame;
			return;
		}
	}

	i = rand() % TLB_SIZE;

	(this -> ctnr)[i].valid = true;
	(this -> ctnr)[i].tag = tag;
	(this -> ctnr)[i].page_frame = page_frame;
	return;
}

static void flush(TLB_t *this) {
	int i;
	for (i = 0; i < TLB_SIZE; ++i) {
		(this -> ctnr)[i].valid = false;
	}
	return;
}

static void disp(TLB_t *this) {
	int i;
	for (i = 0; i < TLB_SIZE; ++i) {
		printf("#%d: valid: %d, tag: 0x%08x, base: 0x%08x\n", i, (this -> ctnr)[i].valid, (this -> ctnr)[i].tag, (this -> ctnr)[i].page_frame);
	}
}

void init_tlb() {
	tlb.init = init;
	tlb.read = read;
	tlb.write = write;
	tlb.flush = flush;
	tlb.disp = disp;
	tlb.init(&tlb);
}
